package week04.question02;

import java.util.concurrent.*;

/**
 * 本周作业：（必做）思考有多少种方式，在main函数启动一个新线程或线程池，
 * * 异步运行一个方法，拿到这个方法的返回值后，退出主线程？
 * * 写出你的方法，越多越好，提交到github。
 *
 *    方案1 Thread.join()   Happens-Before 6 线程的所有操作先于线程中介
 *
 *    基本协作组件
 *    方案2 CountDownLatch()
 *    方案3 Callable + Future
 *    方案4 Runnable + Result + Future
 *    方案5 Runnable + Future
 *
 *    基本同步组件  锁 or 信号量
 *    方案6 LockSupport.park / unpark Happens-Before2 锁规则
 *    方案7 Semaphore 信号量 Happens-Before 3 volatile规则
 *    方案8 自旋 + interrupt Happens-Before 7 线程中断规则
 *
 *    生产者 + 消费者模型  消息队列
 *    方案9   ReentrantLock lock /await+single volatile  和阻塞队列类似  Happens-Before2 锁规则
 *    方案10  数组阻塞队列  ArrayBlockQueue 容量1
 *    方案11  同步队列  SynchronousQueue 容量1
 *    方案12  链表阻塞队列 LinkedBlockQueue  LinkedBlockDeque
 *
 *    管程模型  与9 类似
 *    方案13  synchronized wait + notify  Happens-Before2 锁规则
 *
 *    方案14 CyclicBarrier
 *
 *    方案15 CompletableFuture
 */
public class Answer15 {


    public static void main(String[] args) {

        long start = System.currentTimeMillis();

        // 在这里创建一个线程或线程池，
        // 异步执行 下面方法
        ExecutorService executorService = Executors.newFixedThreadPool(1);


        CompletableFuture<Integer> completableFuture = new CompletableFuture<>();
        executorService.execute(()->{
            completableFuture.complete(sum());
        });

        int result = 0;
        try {
            result = completableFuture.get();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }

        // 确保  拿到result 并输出
        System.out.println("异步计算结果为：" + result);

        System.out.println("使用时间：" + (System.currentTimeMillis() - start) + " ms");

        // 然后退出main线程
        executorService.shutdown();
    }

    private static int sum() {
        return fibo(36);
    }

    private static int fibo(int a) {
        if (a < 2)
            return 1;
        return fibo(a - 1) + fibo(a - 2);
    }
}
